home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 170_01 / cpmfiles.c < prev    next >
Text File  |  1980-01-01  |  10KB  |  355 lines

  1. #include <stdio.h>
  2. #include <telink.h>
  3.  
  4. /* This is a set of replacement functions to make the BDS 'C' compiler
  5. (for CP/M) "unix" compatible.  Each function is described below. 
  6.  
  7. NOTE: You MUST call xinit() at the start of your program to initialize
  8. this file system.
  9.  
  10. All of the names begin with 'x', like xread, xwrite, etc. to distinguish 
  11. them from the BDS functions. You can of course change them to read, write
  12. etc.
  13.  
  14. Change MAXFILES to change the maximum number of files open.
  15.  
  16. The CP/M search first/search next is also supported. It will support only
  17. 128 names. Change MAXNAMES below if necessary.
  18.  
  19.         Tom Jennings 30 June 83
  20.  
  21.     The maximum number of open files is defined by MAXFILES, below.
  22.  
  23. xinit()                Initialize the file system by clearing
  24.                 all handles and counts. MUST be called
  25.                 before any routines are used. Calling it
  26.                 later will abort (not close) all open files.
  27.  
  28. handle= xopen(name,access)    Open the file for reading or writing.
  29. int handle;            'access' is ignored; no text translation
  30. char *name;            is done. Returns -1 if error or file not
  31.                 found.
  32.  
  33. handle= xcreate(name,access)    Similar to above, creates a new file,
  34.                 whose length is zero. Any previous file
  35.                 is deleted.
  36.  
  37. val= xread(handle,buffer,count) Read or write chars to the specified
  38. int val,count,handle;        file. 'val' returns the number of bytes
  39. char *buffer;            actually read; will be == to count if OK,
  40.                 0 if none read.
  41.  
  42. val= xwrite(handle,buffer,count)Same as above, except writes to the open
  43. int val,count,handle;        file. Same returns.
  44. char *buffer;
  45.  
  46. error= xclose(handle)        Close the file. Returns -1 if error. Flushes
  47.                 any data left in the buffer.
  48.  
  49.  
  50. found= xfind(path,name,flag)    Search for filenames. 'flag' should be
  51. int found,flag;            0 for the first call, non-zero there-
  52. char *path,*name;        after. If 'found' returns non-zero, then
  53.                 a filename matching 'path' was found on the
  54.                 disk, and is returned in 'name'. 'path'
  55.                 may contain wildcards and a drive spec.
  56.                 'name' must be 14 chars long. A maximum of
  57.                 MAXNAMES (below) will be handled. The
  58.                 two names are "normal" null terminated names,
  59.                 with a dot if appicable. The drive spec 
  60.                 is stripped off. Upper and lower case is
  61.                 handled by the function.
  62.  
  63.                 NOTE: This works by making the ENTIRE list
  64.                 the 1st time called, and then just returns
  65.                 a previously found name when 'flag' != 0.
  66.                 You CAN make any file open, close, create,
  67.                 read or write calls in between calls to xfind.
  68. */
  69. #define MAXFILES 8        /* max. number of files open at once, */
  70.  
  71. struct _xiobuf {        /* Define the stuff for each file. */
  72.     int hndle;        /* the associated file handle, */
  73.     char fcb[36];        /* The opened FCB, */
  74.     int bufcnt;        /* # bytes in the buffer, */
  75.     char buff[128];        /* the data buffer, */
  76.     int dirty;        /* 1 if written, */
  77. } xfiles[MAXFILES];
  78.  
  79. /* List of found names from the search first/next. */
  80.  
  81. #define MAXNAMES 128        /* maximum number of names for search 
  82.                 first/next. NOTE: 11 bytes per name. */
  83. int numnames;            /* number of names in pile, */
  84. int namenum;            /* current name from pile, */
  85. char names[MAXNAMES][11];    /* where the names are, */
  86.  
  87. /* Initialize the file system. */
  88.  
  89. xinit() {
  90. int i;
  91.  
  92.     for (i= 0; i < MAXFILES; i++)
  93.         xfiles[i].hndle= -1;
  94.     return;
  95. }
  96.  
  97. /* Open a file. Return -1 if file not found, or no handles available. */
  98.  
  99. xopen(name,access)
  100. char *name;
  101. int access;
  102. {
  103. int handle;            /* handle to return to caller, */
  104. int i;
  105.  
  106.     handle= gethandle(-1);    /* find a free handle, */
  107.     if (handle == -1)
  108.         return(handle);    /* none available. */
  109.  
  110.     for (i= 0; i < 36; i++)    /* clear out the FCB, */
  111.         xfiles[handle].fcb[i]= 0;
  112.  
  113.     xfiles[handle].fcb[0]= 0; /* default drive, */
  114.     if (name[1] == ':') {    /* if a drive spec, */
  115.         xfiles[handle].fcb[0]= name[0] - '@';
  116.         ++name; ++name;    /* install it, */
  117.     }
  118.     to_fcb(name,&xfiles[handle].fcb[1]);
  119.     if (bdos(15,&(xfiles[handle].fcb[0])) == 255)
  120.         return(-1);
  121.  
  122.     xfiles[handle].hndle= handle;    /* mark which handle, */
  123.     xfiles[handle].bufcnt= 0;    /* empty buffer, */
  124.     xfiles[handle].dirty= 0;
  125.     return(handle);
  126. }
  127. /* Close the specified file. */
  128.  
  129. xclose(handle)
  130. int handle;
  131. {
  132. int err;
  133.  
  134.     if (gethandle(handle) == -1)
  135.         return(-1);        /* check handle, */
  136.  
  137.     err= 0;                /* assume no error, */
  138.     if (xfiles[handle].dirty) {    /* if stuff in buffer, */
  139.         bdos(26,&xfiles[handle].buff[0]);
  140.         err= bdos(21,&xfiles[handle].fcb[0]) ? -1 : 0;
  141.     }
  142.     xfiles[handle].dirty= 0;
  143.     xfiles[handle].bufcnt= 0;
  144.     xfiles[handle].hndle= 0;
  145.     bdos(16,&xfiles[handle].fcb[0]);    /* close file. */
  146.     return(err);
  147. }
  148. /* Create the specified file. */
  149.  
  150. xcreate(name,access)
  151. char *name;
  152. int access;
  153. {
  154. int handle;
  155. int i;
  156.     handle= gethandle(-1);
  157.     if (handle == -1)
  158.         return(-1);
  159.  
  160.     for (i= 0; i < 36; i++)            /* clear the FCB, */
  161.         xfiles[handle].fcb[i]= 0;
  162.  
  163.     if (name[1] == ':') {            /* if :, then drive, */
  164.         xfiles[handle].fcb[0]= name[0] - '@';
  165.         ++name; ++name;
  166.     } else
  167.         xfiles[handle].fcb[0]= 0;    /* default drive, */
  168.  
  169.     to_fcb(name,&xfiles[handle].fcb[1]);
  170.     xfiles[handle].fcb[12]= '?';        /* delete all extents, */
  171.     bdos(19,&xfiles[handle].fcb[0]);    /* delete file, */
  172.     xfiles[handle].fcb[12]= 0;        /* zero extent, */
  173.     if (bdos(22,&xfiles[handle].fcb[0]) == 255) /* create file, */
  174.         return(-1);
  175.     xfiles[handle].hndle= handle;
  176.     xfiles[handle].bufcnt= 0;
  177.     xfiles[handle].dirty= 0;
  178.     return(handle);
  179. }
  180.  
  181. /* Read from a file. */
  182.  
  183. xread(handle,buffer,count)
  184. int handle;
  185. char *buffer;
  186. int count;
  187. {
  188. int err,i;
  189.  
  190.     i= 0;
  191.     if (gethandle(handle) == -1)
  192.         return(0);
  193.     while (count) {
  194.         if (xfiles[handle].bufcnt) { /* if not empty, */
  195.             *buffer++= xfiles[handle].buff[128 - xfiles[handle].bufcnt--];
  196.             i++;            /* read from buffer, */
  197.             --count;        /* read one, */
  198.         } else {
  199.             bdos(26,&xfiles[handle].buff[0]); /* DMA address, */
  200.             err= bdos(20,&xfiles[handle].fcb[0]);/* fill buffer, */
  201.             if (err)
  202.                 break;
  203.             xfiles[handle].bufcnt= 128;    /* set new count, */
  204.         }
  205.     }
  206.     return(i);
  207. }
  208.  
  209. /* Write chars to the specified file. */
  210.  
  211. xwrite(handle,buffer,count)
  212. int handle;
  213. char *buffer;
  214. int count;
  215. {
  216. int i,err,j;
  217.  
  218.     if (gethandle(handle) == -1)    /* find it first, */
  219.         return(0);        /* doesnt exist! */
  220.  
  221.     i= 0;                /* # byte written, */
  222.     while (count) {
  223.         if (xfiles[handle].bufcnt < 128) {
  224.             xfiles[handle].buff[xfiles[handle].bufcnt++]= *buffer++;
  225.             xfiles[handle].dirty= 1;
  226.             ++i;
  227.             --count;
  228.         } else {
  229.             xfiles[handle].bufcnt= 0; /* buffer empty, */
  230.             xfiles[handle].dirty= 0;  /* buffer written, */
  231.             bdos(26,&xfiles[handle].buff[0]); /* set DMA address, */
  232.             if (bdos(21,&xfiles[handle].fcb[0]))
  233.                 break;
  234.         }
  235.     }
  236.     return(i);            /* return number written, */
  237. }
  238.  
  239. /* Search first/next. The first time causes a disk search, and returns one
  240. name. Search nexts just return one name from the pile. */
  241.  
  242. xfind(path,name,flag)
  243. char *path,*name;
  244. int flag;
  245. {
  246. int i,v;
  247. char *p;
  248.  
  249. if (flag == 0) {            /* if first time, */
  250.  
  251.     numnames= 0;            /* empty list, */
  252.     namenum= 0;            /* start with the 1st. */
  253.     for (i= 0; i < 32; i++)        /* clear out FCB, */
  254.         xffcb[i]= 0;
  255.     for (i= 1; i < 12; i++)        /* blank name, */
  256.         xffcb[i]= ' ';
  257.  
  258.     setfcb(xffcb,path);        /* make an FCB, */
  259.     if ((v= bdos(17,xffcb)) == 255)    /* search first, */
  260.         return(0);        /* no match. */
  261.     do {
  262.         p= cast(0x80 + 1 + (32 * v));
  263.         for (i= 0; i < 12; i++)    /* copy in name only, */
  264.             names[numnames][i]= p[i];
  265.         ++numnames;        /* find all others */
  266.         v= bdos(18,xffcb);    /* search next, */
  267.     } while ((v != 255) && (numnames < MAXNAMES));
  268. }
  269. /* Search next. Just get a name from the list. */
  270.  
  271. if (numnames) {
  272.     from_fcb(names[namenum],name);
  273.     --numnames; ++namenum;
  274.     return(1);
  275. }
  276. return(0);
  277. }
  278. /* Do a type conversion: BDS has no cast operator. */
  279.  
  280. cast(obj)
  281. char *obj;
  282. {    return(obj);
  283. }
  284. /* Look for the handle number in the file structure. Assigned handles
  285. start at 0; unallocated handles are -1. Returns either the handle # 
  286. (index into the structure) or -1 if no match. */
  287.  
  288. gethandle(handle) 
  289. int handle;
  290. {
  291. int i;
  292.     for (i= 0; i < MAXFILES; i++) {
  293.         if (xfiles[i].hndle == handle)
  294.             return(i);
  295.     }
  296.     return(-1);
  297. }
  298. /*